home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / irix / tools / gpasswd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  10.5 KB  |  460 lines

  1. /*------------------------------------------------------------------------
  2.  * $Header: /d1/carlson/programs/misc/RCS/gpasswd.c,v 1.3 1991/07/19 15:33:23 carlson Exp $
  3.  *
  4.  * gpasswd    This program is identical to passwd except sets the
  5.  *         password for a group.
  6.  *
  7.  * Format of call:
  8.  *    gpasswd [group]
  9.  *
  10.  * Where:
  11.  *    group    Is an optional group name to change.  The user must be
  12.  *        in the list of users allowed to be in the group to
  13.  *        change the group password.  If 'group' is not specified,
  14.  *        the user's current group will be assumed.
  15.  *
  16.  * Features:
  17.  *    - If user is root, does not ask for current password.
  18.  *    - If no password exists yet, does not ask for current password.
  19.  *    - If YP entry, keeps it a YP entry.
  20.  *
  21.  * Discussion:
  22.  *  This is just some discussion on how the group password works and
  23.  *  how groups are used in UNIX.
  24.  *
  25.  *  To change groups, the 'newgrp' command is used providing the new
  26.  *  group to be changed to as a parameter.  If the user is root or in
  27.  *  the list in /etc/group for the new group, newgrp starts a new shell
  28.  *  (using whatever shell is the default shell) having the new group
  29.  *  as its group ID.  Note: To return to the old group, all one has to
  30.  *  do is exit the current shell.
  31.  *
  32.  *  If the user is not in the list of accepted users for a group, newgrp
  33.  *  will ask for a password (if one exists in /etc/group).  If no password
  34.  *  exists and the user is not in the list, newgrp will not allow the
  35.  *  change.  If a password is present and the user enters it correctly,
  36.  *  newgrp will start a new shell having the new group as its group ID.
  37.  *
  38.  *
  39.  * Revision History:
  40.  *    $Log: gpasswd.c,v $
  41.  * Revision 1.3  1991/07/19  15:33:23  carlson
  42.  * Added Header for RCS.  Fixed up documentation.
  43.  *
  44.  * Revision 1.2  90/11/27  10:39:57  chris
  45.  * Added debug symbols.
  46.  * 
  47.  * Revision 1.1  90/10/09  17:25:47  chris
  48.  * Initial revision
  49.  * 
  50.  * 11/ 4/89  Christopher W. Carlson - Silicon Graphics Inc.
  51.  * Initial draft
  52.  *
  53.  *-----------------------------------------------------------------------*/
  54.  
  55. #include <stdio.h>
  56. #include <pwd.h>
  57. #include <ctype.h>
  58.  
  59. /*-----
  60.  * DEBUG    Enable debugging so actual group file is NOT modified.
  61.  * DEBUGP    Enable print statements.
  62.  */
  63.  
  64. /* #define DEBUG */
  65. /* #define DEBUGP */
  66.  
  67. typedef enum {FALSE = 0, TRUE} bool;
  68.  
  69. extern char *getlogin (), *getpass (), *index (), *crypt ();
  70.  
  71. #ifdef DEBUG
  72. char grpfil[] = "group";
  73. char tmpfil[] = "$new$group";
  74. #else
  75. char grpfil[] = "/etc/group";
  76. char tmpfil[] = "/etc/$new$group";
  77. #endif
  78.  
  79. char usernam[L_cuserid], grpnam[L_cuserid] = "", newpass[128];
  80. char fline[256], salt[3], ctmp[128];
  81. char ctemp[256], *g_name, *g_pwd, *g_users;
  82. int g_id;
  83. bool YPentry;
  84.  
  85. char charset[] =
  86.       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
  87.  
  88. main (argc, argv)
  89. int argc;
  90. char *argv[];
  91. {
  92.     register int i;        /* Just temporary storage */
  93.     register FILE *ifp, *ofp;    /* For old and new group file */
  94.     int uid, gid;        /* Our UID and GID to change */
  95.     char *login;        /* To know our name */
  96.     struct passwd *cur_pwd;    /* For finding out our name */
  97.     char *cptr;            /* For scanning strings */
  98.     bool b;
  99.  
  100.         /*----
  101.      * Initialize uid with the user ID and gid with the group
  102.      * ID of the process.
  103.      *----*/
  104.  
  105.     uid = getuid ();
  106.     gid = getgid ();
  107.  
  108. #ifdef DEBUGP
  109.     fprintf (stderr, "UID = %d, GID = %d\n", uid, gid);
  110. #endif
  111.  
  112.     /*----
  113.      * Now, figure out the user's name from the UID.
  114.      *----*/
  115.  
  116.     if ((cuserid (usernam) == NULL) || (usernam[0] == '\0')) {
  117.     if ((login = getlogin ()) == NULL) {
  118.         if ((cur_pwd = getpwuid (uid)) == NULL) {
  119.         fprintf (stderr, "gpasswd: Cannot find user name\n");
  120.         exit (1);
  121.         } else {
  122.         strcpy (usernam, cur_pwd->pw_name);
  123.         }
  124.     } else {
  125.         strcpy (usernam, login);
  126.     }
  127.     }
  128.  
  129. #ifdef DEBUGP
  130.     fprintf (stderr, "Username = %s\n", usernam);
  131. #endif
  132.  
  133.     /*----
  134.      * Read the command line parameters.  Only one is expected
  135.      * and this should be a group name.  If no parameter was
  136.      * given, skip saving it.
  137.      *----*/
  138.  
  139.     if (argc > 1) {
  140.     strcpy (grpnam, argv[1]);
  141. #ifdef DEBUGP
  142.     fprintf (stderr, "Group name provided = %s\n", grpnam);
  143. #endif
  144.     }
  145.  
  146.     /*----
  147.      * Open the input group file.
  148.      *----*/
  149.  
  150.     if ((ifp = fopen (grpfil, "r")) == NULL) {
  151.     fprintf (stderr, "gpasswd: Cannot open %s\n", grpfil);
  152.     exit (1);
  153.     }
  154.  
  155.     /*----
  156.      * Open the output group file.  Use a funky name for now.
  157.      *----*/
  158.  
  159.     if ((ofp = fopen (tmpfil, "w")) == NULL) {
  160.     fprintf (stderr, "gpasswd: Cannot create new group file\n");
  161.     exit (1);
  162.     }
  163.  
  164.     /*----
  165.      * Search for desired group entry writing unused entries
  166.      * to output group file.  'b' = TRUE if group entry found.
  167.      *----*/
  168.  
  169.     b = FALSE;
  170.     while (fgets (fline, 256, ifp)) {
  171.  
  172. #ifdef DEBUGP
  173.     fprintf (stderr, "group - %s", fline);
  174. #endif
  175.     parse (fline);
  176.     if (grpnam[0] == '\0') {
  177.         if (gid == g_id) {
  178.         b = TRUE;
  179.         break;
  180.         }
  181.     } else {
  182.         if (strcmp (grpnam, g_name) == 0) {
  183.         b = TRUE;
  184.         break;
  185.         }
  186.     }
  187.     fputs (fline, ofp);
  188.  
  189. #ifdef DEBUGP
  190.     fprintf (stderr, "    skipped\n");
  191. #endif
  192.     }
  193.  
  194.     /*----
  195.      * Verify that the group is good and that the user has the
  196.      * right to change the password.
  197.      *----*/
  198.  
  199.     if (!b) {
  200.     if (grpnam[0] == '\0') {
  201.         fprintf (stderr, "gpasswd: Group entry %d not found\n", gid);
  202.     } else {
  203.         fprintf (stderr, "gpasswd: Group entry %s not found\n", grpnam);
  204.     }
  205.     fclose (ofp);
  206.     unlink (tmpfil);
  207.     exit (1);
  208.     }
  209.  
  210.     if (uid != 0) {        /* If not root */
  211.  
  212. #ifdef DEBUGP
  213.     fprintf (stderr, "Searching user's name\n");
  214. #endif
  215.     b = FALSE;        /* TRUE if user in list */
  216.     for (cptr = g_users; *cptr != '\0'; cptr += strlen (cptr) + 1) {
  217.  
  218. #ifdef DEBUGP
  219.         fprintf (stderr, "   %s...", cptr);
  220. #endif
  221.         if (strcmp (cptr, usernam) == 0) {
  222.  
  223. #ifdef DEBUGP
  224.         fprintf (stderr, "found\n");
  225. #endif
  226.         b = TRUE;
  227.         break;
  228.         }
  229. #ifdef DEBUGP
  230.         fprintf (stderr, "nope\n");
  231. #endif
  232.     }
  233.     if (!b) {
  234.         if (grpnam[0] == '\0') {
  235.         fprintf (stderr,
  236.             "gpasswd: You are not authorized to change the password for %d\n",
  237.              gid);
  238.         } else {
  239.         fprintf (stderr,
  240.             "gpasswd: You are not authorized to change the password for %s\n",
  241.              grpnam);
  242.         }
  243.         fclose (ofp);
  244.         unlink (tmpfil);
  245.         exit (1);
  246.     }
  247.     }
  248.  
  249.     /*----
  250.      * If the user is not root and there is a password, make the
  251.      * user enter the old password.
  252.      *----*/
  253.  
  254.     if (uid != 0) {
  255.     if (*g_pwd != '\0') {
  256.         cptr = getpass ("Enter old password: ");
  257.         strcpy (ctmp, cptr);
  258.         salt[0] = g_pwd[0];
  259.         salt[1] = g_pwd[1];
  260.         salt[2] = '\0';
  261.         cptr = crypt (ctmp, salt);
  262.         if (strcmp (cptr, g_pwd) != 0) {
  263.         fprintf (stderr, "gpasswd: Password incorrect\n");
  264.         fclose (ofp);
  265.         unlink (tmpfil);
  266.         exit (1);
  267.         }
  268.     }
  269.     }
  270.  
  271.     /*----
  272.      * Now have the user enter the new password.  Verify by
  273.      * having him enter it again.
  274.      *----*/
  275.  
  276.     cptr = getpass ("Enter new password: ");
  277.     strcpy (newpass, cptr);
  278.     cptr = getpass ("Enter new password again: ");
  279.  
  280.     if (strcmp (newpass, cptr) != 0) {
  281.     fprintf (stderr, "gpasswd: Passwords don't match\n");
  282.     fclose (ofp);
  283.     unlink (tmpfil);
  284.     exit (1);
  285.     }
  286.  
  287.     /*----
  288.      * Encrypt password.
  289.      *----*/
  290.  
  291.     srand (time (NULL));    /* Randomize random number generator */
  292.     salt[0] = charset[(rand () % sizeof (charset))];
  293.     salt[1] = charset[(rand () % sizeof (charset))];
  294.     salt[2] = '\0';
  295.     cptr = crypt (newpass, salt);
  296.  
  297.     /*----
  298.      * Write new line out.
  299.      *----*/
  300.  
  301.     if (YPentry) {
  302.     sprintf (fline, "+%s:%s:%d:", g_name, cptr, g_id);
  303.     } else {
  304.     sprintf (fline, "%s:%s:%d:", g_name, cptr, g_id);
  305.     }
  306.     for (cptr = g_users; *cptr; cptr += strlen (cptr) + 1) {
  307.     strcat (fline, cptr);
  308.     strcat (fline, ",");
  309.     }
  310.  
  311.     i = strlen (fline) - 1;
  312.     if (fline[i] == ',')
  313.       fline[i] = '\0';
  314.     strcat (fline, "\n");
  315.  
  316.     fputs (fline, ofp);
  317.  
  318.     /*----
  319.      * Now write out rest of file.
  320.      *----*/
  321.  
  322.     while (fgets (fline, 256, ifp)) {
  323.     fputs (fline, ofp);
  324.     }
  325.  
  326.     /*----
  327.      * Close files and rename new one to replace old one.
  328.      *----*/
  329.  
  330.     fclose (ifp);
  331.     fclose (ofp);
  332.     unlink (grpfil);
  333.     rename (tmpfil, grpfil);
  334. }
  335.  
  336. /*--------------------------------------------------------------------------
  337.  * parse    This routine parses the line passed to it assuming it is
  338.  *        of the format for the /etc/group file.  The following
  339.  *        values are set.  Note: String to be parsed is copied to
  340.  *        ctemp in it's entirety.
  341.  *
  342.  *    YPentry    TRUE/FALSE depending on whether line started with "+".
  343.  *    g_name    Points to position in ctemp where group name starts.
  344.  *        Group name string will be terminated with '\0'.
  345.  *    g_pwd    Points to position in ctemp where password begins.
  346.  *        Password string will be terminated with '\0'.
  347.  *    g_users    Points to position in ctemp where first user name is.
  348.  *        Each user name will be null terminated with the next
  349.  *        user name following.  If the first character of the user
  350.  *        name is null, no further user names exist.
  351.  *    g_id    Group ID number.
  352.  *-------------------------------------------------------------------------*/
  353.  
  354. parse (str)
  355.   char *str;
  356. {
  357.     register char *tstr;
  358.  
  359.     /*----
  360.      * Initialize pointers to null string.
  361.      *----*/
  362.  
  363.     YPentry = FALSE;
  364.     g_name = g_pwd = g_users = "";
  365.     g_id = -1;
  366.  
  367.     /*----
  368.      * Copy string to ctemp for parsing.  Also, remove '\n' from
  369.      * end of ctemp.  Set tstr to start of ctemp.
  370.      *----*/
  371.  
  372.     strcpy (ctemp, str);
  373.     if ((tstr = index (ctemp, '\n')))
  374.       *tstr = '\0';
  375.     tstr = ctemp;
  376.  
  377. #ifdef DEBUGP
  378.     fprintf (stderr, "    Parsing %s\n", ctemp);
  379. #endif
  380.  
  381.     /*----
  382.      * Determine if a YP entry.
  383.      *----*/
  384.  
  385.     if (*tstr == '+') {
  386.     YPentry = TRUE;
  387.     tstr++;
  388.     }
  389.  
  390. #ifdef DEBUGP
  391.     fprintf (stderr, "        YPentry = %s\n", (YPentry) ? "TRUE" : "FALSE");
  392. #endif
  393.  
  394.     if (*tstr == '\0')
  395.       return;
  396.  
  397.     /*----
  398.      * Get group name and null terminate.
  399.      *----*/
  400.  
  401.     g_name = tstr;
  402.     tstr = index (tstr, ':');
  403.     if (tstr) {
  404.     *tstr++ = '\0';
  405. #ifdef DEBUGP
  406.     fprintf (stderr, "        group name = %s\n", g_name);
  407. #endif
  408.     } else {
  409. #ifdef DEBUGP
  410.     fprintf (stderr, "        group name = %s\n", g_name);
  411. #endif
  412.     return;
  413.     }
  414.  
  415.     /*----
  416.      * Get password and null terminate.
  417.      *----*/
  418.  
  419.     g_pwd = tstr;
  420.     tstr = index (tstr, ':');
  421.     if (tstr) {
  422.     *tstr++ = '\0';
  423. #ifdef DEBUGP
  424.     fprintf (stderr, "        password = %s\n", g_pwd);
  425. #endif
  426.     } else {
  427. #ifdef DEBUGP
  428.     fprintf (stderr, "        password = %s\n", g_pwd);
  429. #endif
  430.     return;
  431.     }
  432.  
  433.     /*----
  434.      * Get group ID and null terminate.
  435.      *----*/
  436.  
  437.     g_id = atoi (tstr);
  438.     tstr = index (tstr, ':');
  439.     if (tstr) {
  440.     *tstr++ = '\0';
  441. #ifdef DEBUGP
  442.     fprintf (stderr, "        ID = %d\n", g_id);
  443. #endif
  444.     } else {
  445. #ifdef DEBUGP
  446.     fprintf (stderr, "        ID = %d\n", g_id);
  447. #endif
  448.     return;
  449.     }
  450.  
  451.     /*----
  452.      * Get list of users and null terminate.
  453.      *----*/
  454.  
  455.     g_users = tstr;
  456.     while ((tstr = index (tstr, ','))) {
  457.     *tstr++ = '\0';
  458.     }
  459. }
  460.